昨天建立ONOS控制器的環境與ONOS APP的開發環境,今天會介紹如何撰寫一般switch轉發的功能
實做前需要了解幾項OSON提供的物件
ONOS應用程式中的生命週期,activate()代表著服務的開始,要先與控制器註冊。
先實例化SwitchPacketProcessor物件,裡面有時做PacketProcessor的抽象類別,當有封包通過時則會觸發該方法。
此APP是實做轉發功能的工作,只處理PV4與ARP的package,所以預先限制。
@Activate
protected void activate() {
appId = coreService.getAppId("org.foo.app"); //與pom.xml檔案中的名字相同
processor = new SwitchPacketProcessor();
packetService.addProcessor(processor, PacketProcessor.director(3));
/*
* 限制packet類型為IPV4與ARP
*/
packetService.requestPackets(DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4).build(), PacketPriority.REACTIVE, appId, Optional.empty());
packetService.requestPackets(DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_ARP).build(), PacketPriority.REACTIVE, appId, Optional.empty());
}
剛剛提到的SwitchPacketProcessor類別因實做PacketProcessor需覆寫process方法,在裡面有呼叫兩個方法,initMacTable與actLikeSwitch。
而initMacTable的目的為實做一般switch上紀錄mac表,macTables變數紀錄者那一台裝置(switch)上的來源的mac與來源port。
private class SwitchPacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext pc) {
initMacTable(pc.inPacket().receivedFrom());
actLikeSwitch(pc);
}
protected Map<DeviceId, Map<MacAddress, PortNumber>> macTables = Maps.newConcurrentMap();
private void initMacTable(ConnectPoint cp) {
macTables.putIfAbsent(cp.deviceId(), Maps.newConcurrentMap());
}
在process方法裡呼叫的actLikeSwitch方法其目的流程:
public void actLikeSwitch(PacketContext pc) {
Short type = pc.inPacket().parsed().getEtherType();
if (type != Ethernet.TYPE_IPV4 && type != Ethernet.TYPE_ARP) {
return;
}
ConnectPoint cp = pc.inPacket().receivedFrom();
Map<MacAddress, PortNumber> macTable = macTables.get(cp.deviceId());
MacAddress srcMac = pc.inPacket().parsed().getSourceMAC();
MacAddress dstMac = pc.inPacket().parsed().getDestinationMAC();
macTable.put(srcMac, cp.port());
PortNumber outPort = macTable.get(dstMac);
if (outPort != null) {
pc.treatmentBuilder().setOutput(outPort);
FlowRule fr = DefaultFlowRule.builder()
.withSelector(DefaultTrafficSelector.builder().matchEthDst(dstMac).build())
.withTreatment(DefaultTrafficTreatment.builder().setOutput(outPort).build())
.forDevice(cp.deviceId()).withPriority(PacketPriority.REACTIVE.priorityValue())
.makeTemporary(60)
.fromApp(appId).build();
flowRuleService.applyFlowRules(fr);
pc.send();
} else {
actLikeHub(pc);
}
}
public void actLikeHub(PacketContext pc) {
pc.treatmentBuilder().setOutput(PortNumber.FLOOD);
pc.send();
}
最後在應用程式刪除時,調用deactivate刪除PacketProcessor
@Deactivate
protected void deactivate() {
packetService.removeProcessor(processor);
}
將應用程式編譯,並推送到控制器上
source $ONOS_ROOT/tools/dev/bash_profile
mvn clean install
onos-app <control ip> reinstall target/foo-app-1.0-SNAPSHOT.oar
mn --controller=remote,ip=<control ip> --mac --topo=single,2 --switch ovsk,protocols=OpenFlow13
可以登入到ONOS dashboard
http:// (control ip) :8181/onos/ui/
帳號 onos 密碼 rocks
安裝必要與剛剛撰寫的APP
需要安裝 APP ID為org.onosproject.openflow 以啟用openflow協定
找到自己的APP ID本篇為org.foo.app
使用ping工具測試其結果
查看dashboard上所顯示的網路拓樸
查看dashboard上所顯示產生的Flow規則
https://github.com/opennetworkinglab/onos